#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QTextCodec>
#include <QFileDialog>
#include <QQueue>
#include <QTime>

#include <QObject>
#include <QTcpSocket>
#include <QTcpServer>
#include <QHostAddress>

#include <QtNetwork/QUdpSocket>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QNetworkInterface>
#include <QtNetwork/QNetworkAddressEntry>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>

#include <QHostAddress>
#include <QNetworkInterface>
#include <QAbstractSocket>


#include "crc.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

#define DSPQUERY    0x202255aa
#define DSPSTART    0x202355aa
#define DSPFIRWARE  0x202455aa
#define DSPTAIL     0x0022


#define WINGQUERY   0x2022aa55
#define WINGSTART   0x2023aa55
#define WINGFIRWARE 0x2024aa55
#define WINGTAIL    0x0022





#pragma pack(push) //保存对齐状态
#pragma pack(1)//设定为1字节对齐

#define WING_MAX_SIZE   65536
struct cmdStruct {
    // 包头。
    uint32_t uHeader;
    // 升级包的类型。
    uint32_t uType;
    // 数据包大小
    uint32_t uSize;
    // 包尾。
    uint32_t uTail = 0x0022;
    //CRC32校验
    uint32_t uCrc32;
    //数据实体
    uint8_t uFirware[WING_MAX_SIZE];//4个字节表示偏移地址
};


#define BOOTLOADER_SIZE (20*1024*1024) //20M
struct bootloaderParams {
    uint16_t uType;
    uint32_t uDataSize;
    uint32_t uSubPackageSize;
    uint32_t uCrc32;
    uint32_t uSendLen;
    bool state;
    uint16_t timeout;
    uint16_t timeout_cnt;
    QString uPackageName;
    QByteArray uWingsCache;//固件保存缓存
//    uint8_t uWingsCache[BOOTLOADER_SIZE];
};

#pragma pack(pop)

struct sessionStruct {
    QString uMode;
    QString uSendAddr;
    qint64 uSendPort;
    QString uLocalAddr;
    qint64 uLocalPort;
};

typedef struct{
    QHostAddress ip;
    quint16 port;
    QByteArray msg;
}uReciver;




class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    bootloaderParams networkBootloaderStruct;
    cmdStruct bootloadSend;
    sessionStruct sessionInfo;


    qint64 udpWrite(QString remoteIp,qint64 remotePort,QByteArray sMsg);
    void udpInit(QString localIp,qint64 localPort);

    void setComboBoxIp();
    int splitData(QString remoteIp,qint64 remotePort,unsigned char* msg,quint64 nLen);
    void sleep(unsigned int msec);
    void confBootloadData(QString path);
    qint64 firwareSendto(struct cmdStruct *cmd);
    void setProgressBar(uint32_t val);

private slots:
    void on_pushButton_2_clicked();

    void on_pushButton_4_clicked();

    void on_pushButton_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_5_clicked();

    void on_comboBox_currentIndexChanged(const QString &arg1);

    void slotReadDatagrams();
    void on_pushButton_6_clicked();

private:
    Ui::MainWindow *ui;
    QTextCodec * ui_codec = QTextCodec::codecForName("gbk");
    QString getMyIpString();
    void checkNetwork();
    QQueue<QByteArray> udpQueue;
    QStringList ipAddressList;
    QUdpSocket *udpSend;
    QUdpSocket *udpRev;
    uReciver mReciver;
    bool webConnect = false;


public:

    QQueue<QByteArray> tcpQueue;
    void tcpClientInit(QString remoteIp,qint64 remotePort);
    void tcpServerInit(QString remoteIp,qint64 remotePort);
    void tcpDisconnect();
    void tcpWrite(QByteArray sMsg);

public:
    // 定时发送-定时器
        QTimer *timSend;
        int timer_id;
        void timerEvent(QTimerEvent * ev);

public:
        void networkDecode(QByteArray recBuf);
        void networkBootloaderSend(QByteArray recBuf);
        void networkBootloaderVersion(QByteArray recBuf);
        void networkBootloaderFirst(QByteArray recBuf);


private:
    QTcpSocket *mTcpSocket = nullptr;//tcp套接字
    QTcpServer* mTcpServe = nullptr;    //tcp服务端
//TCP连接服务
private slots:
    void onConnected();
    void onDisConnected();
    void onStateChanged(QAbstractSocket::SocketState);
    void onReadyRead();
    void displayError(QAbstractSocket::SocketError socketError);

    void onNewConnect();    //客户端新的连接请求处理
    void onSendBackMsg();   //反馈信息给客户端新的连接
    void onReadMsg();       //服务端读取客户端发来的数据
};

extern QQueue<QByteArray> mudp_queue;
#endif // MAINWINDOW_H
